#!/usr/bin/env python
"""
Label the raw dataset of user weiboes.
"""
import concurrent.futures
import traceback
from SpideUserPosts import WeiboGenerator
from utils import Util, DBUtils, WeiboSample, PageConfigInfo, __DEBUG__

class WeiboSampleGenerator:
    """
    Generates positive samples and negative samples according
    to a specific reposts.
    """
    def __init__(self, db_con, uid):
        self.db_con = db_con
        self.uid = uid

    def run(self):
        """
        Take care of the processing logic
        """
        cursor = self.db_con.cursor()
        cursor.execute("""select last_uid, last_pid, last_domain from user_reposts where uid = %s
                group by last_uid, last_pid, last_domain;""", (self.uid,))
        last_users = cursor.fetchall()
        conf = PageConfigInfo()
        negative_samples = {'repost': [], 'post': []}
        for last_user in last_users: 
            conf.uid = last_user[0]
            conf.page_id = last_user[1]
            conf.domain = last_user[2]
            cursor.execute("""select time from user_reposts where uid = %s and last_uid = %s group by
                    time;""", (self.uid, conf.uid))
            time = [t[0] for t in cursor.fetchall()]
            reposts, posts = self._spideBefore(conf, time[0]) 

            for repost in reposts:
                if repost.time not in time:
                    negative_samples['repost'].append(repost)
            for post in posts:
                if post.time not in time:
                    negative_samples['post'].append(post)
            break
        cursor.close()
        positive_samples = self._generatePositiveSamples() 
        self._persistPositiveSamples(positive_samples)
        self._persistNegativeSamples(negative_samples)
        return self.uid

    def _generatePositiveSamples(self):
        """
        Load the current user's reposts. And do some cleans.
        """
        if __DEBUG__:
            print("Generating and cleaning positive samples")
        cursor = self.db_con.cursor()
        cursor.execute("""select last_uid, uid, content, time from 
                user_reposts where uid = %s;""", (self.uid,))
        samples = []
        for repost in cursor.fetchall():
            sample = WeiboSample()
            sample.last_uid = repost[0]
            sample.uid = repost[1]
            sample.content = repost[2]
            sample.time = repost[3]
            samples.append(sample)
        cursor.close()
        return samples

    def _spideBefore(self, conf, time):
        """
        Spide user weibo posted before the specified time, but the entire time span
        should be in a month.
        """
        if __DEBUG__:
            print("Start spiding weibo of the last hop before " + time)
        time = Util.timeToInt(time)
        return WeiboGenerator(conf.uid, conf.page_id, conf.domain, time-1000000, time, db_con)._spide()


    def _persistPositiveSamples(self, positive_samples):
        """
        Label the input samples and dump them to the local storage.
        The sample form should be:
            <last_uid, uid, content, time, True>
        """
        if __DEBUG__:
            print("Start persisting positive samples")
        cursor = self.db_con.cursor()
        for sample in positive_samples:
            cursor.execute("""insert into repost_samples (last_uid, uid, content, time, is_repost)
                    values (%s, %s, %s, %s, %s);""", (sample.last_uid, sample.uid, sample.content,
                    sample.time, True))
        cursor.close()
        db_con.commit()


    def _persistNegativeSamples(self, negative_samples):
        """
        Label the input samples and dump them to the local storage.
        The sample form should be:
            <last_uid, uid, content, time, False>
        """
        if __DEBUG__:
            print("Start persisting negative samples")
        cursor = self.db_con.cursor()
        for sample in negative_samples['repost']:
            cursor.execute("""insert into repost_samples (last_uid, uid, content, time, is_repost)
                    values (%s, %s, %s, %s, %s);""", (sample.uid, self.uid, sample.content,
                    sample.time, False))
        db_con.commit()
        for sample in negative_samples['post']:
            cursor.execute("""insert into repost_samples (last_uid, uid, content, time, is_repost)
                    values (%s, %s, %s, %s, %s);""", (sample.uid, self.uid, sample.content,
                    sample.time, False))

if __name__ == '__main__':
    db_con = DBUtils.initdb()
    cursor = db_con.cursor()
    cursor.execute("""select uid from user_reposts group by uid;""")
    uids = cursor.fetchall()
    cursor.close()
    finished = []
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = dict()
        for uid in uids:
            if __DEBUG__:
                print("Submmit task: " + str(uid[0]))
            futures[executor.submit(WeiboSampleGenerator(
                    db_con, uid[0]).run)] = uid 
        for future in concurrent.futures.as_completed(futures):
            try:
                finished.append(future.result())
            except Exception:
                traceback.print_exc()
    print("Finished tasks: " + str(finished))





